const { Service } = require("egg");

class DirectoryArticleService extends Service {
  async all(directoryId) {
    const { ctx } = this;
    const datas = await ctx.model.DirectoryArticle.findAll({
      raw: true,
      where: {
        directoryId,
      },
    });
    return datas;
  }

  async listQuery({ directoryId, pageNum, pageSize, search }) {
    const { ctx, app } = this;
    const { Op } = app.Sequelize;
    const offset = (pageNum - 1) * pageSize;

    let where = { directoryId };
    if (search) {
      where = {
        ...where,
        "$article.title$": {
          [Op.like]: `%${search}%`,
        },
      };
    }
    const total = await ctx.model.DirectoryArticle.count({
      where: where,
      include: [{ model: ctx.model.Article, as: "article" }],
    });

    const directoryArticles = await ctx.model.DirectoryArticle.findAll({
      where: where,
      include: [
        {
          model: ctx.model.Article,
          as: "article",
          attributes: { exclude: ["detail"] },
        },
      ],
      offset,
      limit: pageSize,
      order: [
        ["isTop", "DESC"],
        [{ model: ctx.model.Article, as: "article" }, "publishTime", "DESC"],
      ],
    });
    const sorts = directoryArticles.map((item) => ({
      ...item.dataValues,
    }));

    return {
      total,
      hasNextPage: offset + pageSize < total,
      sorts,
      pageNum,
      pageSize,
    };
  }

  async getDataByIds(ids) {
    const { ctx, app } = this;
    const { Op } = app.Sequelize;
    let where = { directoryId: { [Op.in]: ids } };
    const directoryArticles = await ctx.model.DirectoryArticle.findAll({
      where: where,
      include: [
        {
          model: ctx.model.Article,
          as: "article",
          attributes: { exclude: ["detail"] },
        },
      ],
      order: [
        ["isTop", "DESC"],
        [{ model: ctx.model.Article, as: "article" }, "publishTime", "DESC"],
      ],
    });
    let categorizedResults = directoryArticles.reduce((acc, curr) => {
      const key = curr.dataValues.directoryId;
      if (!acc[key]) {
        acc[key] = [];
      }
      acc[key].push(curr.dataValues);
      return acc;
    }, {});

    const sortedResults = Object.entries(categorizedResults).map(([directoryId, list]) => ({
      directoryId: parseInt(directoryId), // 确保directoryId是数字类型
      list,
    }));


    return sortedResults;
 

  }



  async findOne(where) {
    const { ctx } = this;

    return await ctx.model.DirectoryArticle.findOne({
      where,
    });
  }

  async bind({ articleId, directoryId }) {
    return await this.ctx.model.DirectoryArticle.create({
      articleId,
      directoryId,
    });
  }

  async delete(articleId, directoryId) {
    return await this.ctx.model.DirectoryArticle.destroy({
      where: { articleId, directoryId },
    });
  }

  async setTop({ articleId, directoryId }) {
    const { ctx } = this;
    const MAX_TOP_ARTICLES = 10;

    const maxIsTopResult = await ctx.model.DirectoryArticle.findOne({
      order: [["isTop", "DESC"]],
      where: {
        directoryId,
      },
      raw: true,
    });
    const topCount = maxIsTopResult ? maxIsTopResult.isTop : 0;

    if (topCount >= MAX_TOP_ARTICLES) {
      const articles = await ctx.model.DirectoryArticle.findAll({
        raw: true,
        where: {
          isTop: {
            [ctx.app.Sequelize.Op.gt]: 0,
          },
          directoryId,
        },
        order: [["isTop", "DESC"]],
      });
      const topArticles = articles.slice(0, MAX_TOP_ARTICLES - 1);
      const restArticles = articles.slice(MAX_TOP_ARTICLES - 1);

      for (let i = 0; i < topArticles.length; i++) {
        await ctx.model.DirectoryArticle.update(
          { isTop: topArticles.length - i },
          {
            where: { id: topArticles[i].id },
          }
        );
      }

      for (const article of restArticles) {
        await ctx.model.DirectoryArticle.update(
          { isTop: 0 },
          {
            where: { id: article.id },
          }
        );
      }
    }
    await ctx.model.DirectoryArticle.update(
      { isTop: Math.min(MAX_TOP_ARTICLES, topCount + 1) },
      { where: { articleId, directoryId } }
    );
  }

  async cancelTop({ articleId, directoryId }) {
    const { ctx } = this;

    await ctx.model.DirectoryArticle.update(
      { isTop: 0 },
      { where: { articleId, directoryId } }
    );
  }
}
module.exports = DirectoryArticleService;
